using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
// ReSharper disable CheckNamespace

// 反射特性，用于标记需要自动注入的静态字段
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
public sealed class ReflectionAttribute : Attribute
{
    public Type TargetType { get; }
    public string? TargetName { get; }
    public BindingFlags Flags { get; }

    private ReflectionAttribute(Type targetType, string? targetName, BindingFlags flags)
    {
        TargetType = targetType;
        TargetName = targetName;
        Flags = flags;
    }

    // 修改：使 targetName 变为可选参数，默认为 null
    public ReflectionAttribute(Type targetType, string? targetName = null)
        : this(targetType, targetName, BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
    {
    }

    public ReflectionAttribute(Type targetType, BindingFlags flags)
        : this(targetType, null, flags)
    {
    }
}

// 自动反射管理类（修改了 InjectReflection 方法）
public static class AutoReflection
{
    private static readonly HashSet<Assembly> InitializedAssemblies = new HashSet<Assembly>();
    private static readonly object LockObject = new object();

    public static void Initialize()
    {
        Initialize(Assembly.GetCallingAssembly());
    }
    
    /// <summary>
    /// 初始化程序集，扫描并注入带有Reflection特性的静态字段
    /// </summary>
    /// <param name="assembly">要初始化的程序集</param>
    public static void Initialize(Assembly? assembly)
    {
        if (assembly == null)
        {
            Debug.LogWarning("[AutoReflection] 空的目标程序集");
            return;
        }

        lock (LockObject)
        {
            // 如果已经初始化过，直接返回
            if (!InitializedAssemblies.Add(assembly))
            {
                Debug.LogWarning($"[AutoReflection] {assembly.GetName()} 重复初始化");
                return;
            }
        }

        Debug.Log($"[AutoReflection] 开始对 {assembly.GetName()} 的字段进行反射注入...");

        // 扫描并处理所有类型
        foreach (var type in assembly.GetTypes())
        {
            ProcessType(type);
        }

        Debug.Log($"[AutoReflection] 对 {assembly.GetName()} 的字段反射注入完毕");
    }

    private static void ProcessType(Type type)
    {
        // 获取所有静态字段
        var fields = type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);

        foreach (var field in fields)
        {
            // 检查是否有Reflection特性
            var reflectionAttr = field.GetCustomAttribute<ReflectionAttribute>();
            if (reflectionAttr != null)
            {
                InjectReflection(field, reflectionAttr);
            }
        }
    }

    private static void InjectReflection(FieldInfo field, ReflectionAttribute attribute)
    {
        try
        {
            var targetType = attribute.TargetType;
            
            // 修改：如果 TargetName 为空，使用字段名作为目标名
            var targetName = string.IsNullOrEmpty(attribute.TargetName) 
                ? field.Name 
                : attribute.TargetName;
                
            var flags = attribute.Flags == BindingFlags.Default ?
                GetDefaultBindingFlags(field) : attribute.Flags;

            object? reflectionResult = null;

            // 根据字段类型决定反射的目标
            if (field.FieldType == typeof(FieldInfo))
            {
                reflectionResult = targetType.GetField(targetName, flags);
            }
            else if (field.FieldType == typeof(PropertyInfo))
            {
                reflectionResult = targetType.GetProperty(targetName, flags);
            }
            else if (field.FieldType == typeof(MethodInfo))
            {
                reflectionResult = targetType.GetMethod(targetName, flags);
            }
            else if (field.FieldType == typeof(ConstructorInfo))
            {
                var constructors = targetType.GetConstructors(flags);
                // 修改：如果目标名为空，获取无参构造函数；否则按名称查找特定构造函数
                if (string.IsNullOrEmpty(attribute.TargetName))
                {
                    reflectionResult = constructors.FirstOrDefault(c => c.GetParameters().Length == 0);
                }
                else
                {
                    // 可以扩展这里来支持按参数类型查找特定构造函数
                    reflectionResult = constructors.FirstOrDefault(c => 
                        c.Name == targetName || c.ToString().Contains(targetName));
                }
            }
            else if (field.FieldType == typeof(EventInfo))
            {
                reflectionResult = targetType.GetEvent(targetName, flags);
            }
            else if (field.FieldType == typeof(Type))
            {
                reflectionResult = targetType.GetNestedType(targetName, flags) ??
                                 Assembly.GetAssembly(targetType)?.GetType(targetName);
            }
            else if (field.FieldType == typeof(MemberInfo))
            {
                // 尝试按顺序查找：字段、属性、方法、事件
                reflectionResult = targetType.GetField(targetName, flags) as MemberInfo ??
                                 targetType.GetProperty(targetName, flags) as MemberInfo ??
                                 targetType.GetMethod(targetName, flags) as MemberInfo ??
                                 targetType.GetEvent(targetName, flags);
            }

            // 如果找到反射结果且不为空，则注入字段
            if (reflectionResult != null)
            {
                field.SetValue(null, reflectionResult);
                Debug.Log(
                    $"[AutoReflection] 成功注入: {field.DeclaringType?.Name}.{field.Name} -> {targetType.Name}.{targetName}");
            }
            else
            {
                Debug.LogWarning(
                    $"[AutoReflection] 注入 {field.DeclaringType?.Name}.{field.Name} -> {targetType.Name}.{targetName} 时未找到目标: ");
            }
        }
        catch (Exception ex)
        {
            Debug.LogError($"[AutoReflection] 反射'{attribute.TargetType}.{attribute.TargetName}'时出错: {ex.Message}");
        }
    }

    private static BindingFlags GetDefaultBindingFlags(FieldInfo field)
    {
        var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;

        // 根据字段的可访问性决定是否包含实例成员
        if (field.IsPublic || field.IsAssembly || field.IsFamilyOrAssembly)
        {
            flags |= BindingFlags.Instance;
        }

        return flags;
    }

    /// <summary>
    /// 检查程序集是否已经初始化
    /// </summary>
    public static bool IsInitialized(Assembly assembly)
    {
        lock (LockObject)
        {
            return InitializedAssemblies.Contains(assembly);
        }
    }
}